# 参数：*args 用来将参数打包成tuple给函数体调用， **kwargs 打包关键字参数成dict给函数体调用
# 注意点：参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序，否则程序会报错。
def fun(arg, *args, **kwargs):
    # 元组tuple
    a = (1, 2, 3, 4, 5)
    print('元组：', a)

    # 列表list
    b = [1, 2, 3, 4, 5]
    print('列表：', b)

    # 字典dict
    c = {1: 101, 2: 102, 3: 103}
    print('键：', c.keys())
    print('值：', c.values())

    print('位置参数：', arg)  # 位置参数
    print('可变参数：', *args)  # 可变参数
    print('键值参数：', kwargs)  # 键值参数(关键字参数)：对于传入的参数名无法限制


# 命名关键字参数：*右边为关键字参数，调用的时候必须要传入参数名，否则会报错
def fun1(arg, *, n, m):
    print(arg, n, m)


# 参数组合使用
def fun2(a, num=90, *arg, **kwargs):
    print(a)
    print(num)
    print(*arg)
    print(kwargs)


def fun3(arg, num=100, *, b, **keargs):
    print(arg)
    print(num)
    print(b)
    print(keargs)


def foo():
    print('starting......')
    while True:
        res = yield 4
        print('res:', res)


# 包含yield语句的函数是一个生成器
# 生成器每次产生一个值（yield语句），函数被冻结，被唤醒后再产生一个值
# 生成器是一个不断产生值的函数
def fun_yield():
    yield 1


def fun_yield1():
    print('1001')
    m = yield 1
    print('m：', m)
    d = yield 2
    print('world')


def fun_yield2():
    print('1002')
    m = yield 1
    print('m：', m)
    d = yield 2
    print('world')


# 一般写法
def square(n):
    ls = [i**2 for i in range(n)]
    return ls


# 迭代器写法
def gen(n):
    for i in range(n):
        yield i**2

def yield_from():
    num=(1,2,3,4,5,6)
    # for i in num:
    #     yield i
    yield from num


def yield_from2_1():
    for i in range(3):
        yield i
    return 2021


def yield_from2_2():
    a = yield from yield_from2_1()
    print('a = {}'.format(a))

if __name__ == '__main__':
    fun(1, 2, 3, 4, 5, b=2, c=3, d=4)
    fun1(1, n=12, m=13)
    fun2(1, 2, 3, 4, 5, b=6, c=7, d=8)
    fun3(1,  b=6, c=7, d=8)

    g = foo()  # 执行到yield结束
    print(next(g))  # 在yield下一条语句开始执行
    print('*'*10)
    print(next(g))

    f = fun_yield()
    print(f)
    for i in f:
        print(i)
    print('*'*10)

    f = fun_yield1()
    print(next(f))
    print(next(f))
    print('*'*10)

    f = fun_yield2()
    rs1 = next(f)
    print(rs1)
    rs2 = f.send('1800')# 继续执行上次暂停的生成器，并传参数给m
    print(rs2)
    print('*'*20)

    # for i in square(10000):
    #     print(i, end=' ')

    # for i in gen(10000):
    #     print(i, end=' ')

    # yield from代替for循环
    for x in yield_from():
        print(x,end=',')

    # yield from 还可以接受生成器的返回值，我们知道生成器是通过yield来返回值的，return的值是无法通过for 迭代生成器来获得的，var = yield from 可以获取return
    for item in yield_from2_2():
        print(item)
